using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using twistmachinev2.Entity;
using twistmachinev2.Repository;

namespace twistmachinev2.OPCUA
{
    /// <summary>
    /// OPCUA配置服务类 - 基于数据库的配置管理
    /// </summary>
    public class OpcUaConfigService : IDisposable
    {
        private OPCUARepository _repository;
        private bool _disposed = false;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="repository">数据库仓储</param>
        public OpcUaConfigService(OPCUARepository repository)
        {
            _repository = repository ?? throw new ArgumentNullException(nameof(repository));
        }

        /// <summary>
        /// 构造函数 - 使用默认数据库路径
        /// </summary>
        /// <param name="dbPath">数据库文件路径（可选，为空时使用配置文件中的路径）</param>
        public OpcUaConfigService(string dbPath = null)
        {
            if (string.IsNullOrEmpty(dbPath))
            {
                // 使用BaseData中配置的连接字符串
                _repository = new OPCUARepository();
            }
            else
            {
                // 使用指定的数据库路径
                string connectionString = $"Data Source={dbPath}";
                _repository = new OPCUARepository(connectionString);
            }
        }

        #region 服务器配置管理

        /// <summary>
        /// 获取OPCUA服务器配置
        /// </summary>
        /// <returns>服务器配置</returns>
        public OpcUaServerConfigEntity GetServerConfig()
        {
            try
            {
                return _repository.GetOpcUaServerConfig();
            }
            catch
            {
                // 如果没有配置，返回默认配置
                return GetDefaultServerConfig();
            }
        }

        /// <summary>
        /// 获取服务器URL
        /// </summary>
        /// <returns>服务器URL</returns>
        public string GetServerUrl()
        {
            var config = GetServerConfig();
            return config?.ServerUrl ?? "opc.tcp://127.0.0.1:49320";
        }

        /// <summary>
        /// 获取服务器用户名
        /// </summary>
        /// <returns>用户名</returns>
        public string GetUsername()
        {
            var config = GetServerConfig();
            return config?.Username ?? string.Empty;
        }

        /// <summary>
        /// 获取服务器密码
        /// </summary>
        /// <returns>密码</returns>
        public string GetPassword()
        {
            var config = GetServerConfig();
            return config?.Password ?? string.Empty;
        }

        /// <summary>
        /// 保存服务器配置
        /// </summary>
        /// <param name="serverUrl">服务器URL</param>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <returns>保存成功返回true</returns>
        public bool SaveServerConfig(string serverUrl, string username = "", string password = "")
        {
            // 先尝试获取现有配置
            var existingConfig = _repository.GetOpcUaServerConfig();
            
            OpcUaServerConfigEntity config;
            if (existingConfig != null)
            {
                // 更新现有配置
                config = existingConfig;
                config.ServerUrl = serverUrl;
                config.Username = username;
                config.Password = password;
                config.IsEnabled = true;
                config.Remark = "通过配置服务更新";
            }
            else
            {
                // 创建新配置
                config = new OpcUaServerConfigEntity
                {
                    ServerUrl = serverUrl,
                    Username = username,
                    Password = password,
                    IsEnabled = true,
                    Remark = "通过配置服务保存"
                };
            }

            return _repository.SaveOpcUaServerConfig(config);
        }

        /// <summary>
        /// 保存服务器配置（重载方法 - 接受实体对象）
        /// </summary>
        /// <param name="serverConfig">服务器配置实体</param>
        /// <returns>保存成功返回true</returns>
        public bool SaveServerConfig(OpcUaServerConfigEntity serverConfig)
        {
            if (serverConfig == null)
                return false;

            return _repository.SaveOpcUaServerConfig(serverConfig);
        }

        /// <summary>
        /// 获取默认服务器配置
        /// </summary>
        /// <returns>默认服务器配置</returns>
        private OpcUaServerConfigEntity GetDefaultServerConfig()
        {
            return new OpcUaServerConfigEntity
            {
                ServerUrl = "opc.tcp://127.0.0.1:49320",
                Username = "",
                Password = "",
                IsEnabled = true
            };
        }

        #endregion

        #region 节点配置管理

        /// <summary>
        /// 获取所有节点配置
        /// </summary>
        /// <returns>节点配置列表</returns>
        public List<OpcUaNodeConfigEntity> GetAllNodes()
        {
            return _repository.GetAllOpcUaNodeConfigs();
        }

        /// <summary>
        /// 根据节点ID获取配置
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <returns>节点配置</returns>
        public OpcUaNodeConfigEntity GetNodeConfig(string nodeId)
        {
            return _repository.GetOpcUaNodeConfigByNodeId(nodeId);
        }

        /// <summary>
        /// 根据分组获取节点配置
        /// </summary>
        /// <param name="group">分组名称</param>
        /// <returns>节点配置列表</returns>
        public List<OpcUaNodeConfigEntity> GetNodesByGroup(string group)
        {
            return _repository.GetOpcUaNodeConfigsByGroup(group);
        }

        /// <summary>
        /// 获取订阅的节点配置
        /// </summary>
        /// <returns>订阅的节点配置列表</returns>
        public List<OpcUaNodeConfigEntity> GetSubscribedNodes()
        {
            return GetAllNodes().Where(x => x.IsSubscribed).ToList();
        }

        /// <summary>
        /// 添加节点配置
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        /// <returns>添加成功返回true</returns>
        public bool AddNode(OpcUaNodeConfigEntity nodeConfig)
        {
            // 检查是否已存在相同的NodeId
            try
            {
                var existing = GetNodeConfig(nodeConfig.NodeId);
                if (existing != null)
                {
                    throw new ArgumentException($"节点ID {nodeConfig.NodeId} 已存在");
                }
            }
            catch (InvalidOperationException)
            {
                // 节点不存在，可以添加
            }

            return _repository.SaveOpcUaNodeConfig(nodeConfig);
        }

        /// <summary>
        /// 更新节点配置
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        /// <returns>更新成功返回true</returns>
        public bool UpdateNode(OpcUaNodeConfigEntity nodeConfig)
        {
            return _repository.SaveOpcUaNodeConfig(nodeConfig);
        }

        /// <summary>
        /// 删除节点配置
        /// </summary>
        /// <param name="id">配置ID</param>
        /// <returns>删除成功返回true</returns>
        public bool RemoveNode(int id)
        {
            return _repository.DeleteOpcUaNodeConfig(id);
        }

        /// <summary>
        /// 批量保存节点配置
        /// </summary>
        /// <param name="nodeConfigs">节点配置列表</param>
        /// <returns>保存成功的行数</returns>
        public int SaveNodes(List<OpcUaNodeConfigEntity> nodeConfigs)
        {
            return _repository.SaveOpcUaNodeConfigs(nodeConfigs);
        }

        /// <summary>
        /// 保存节点配置（兼容方法）
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        /// <returns>保存成功返回true</returns>
        public bool SaveNodeConfig(OpcUaNodeConfigEntity nodeConfig)
        {
            return _repository.SaveOpcUaNodeConfig(nodeConfig);
        }

        /// <summary>
        /// 更新节点配置（兼容方法）
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        /// <returns>更新成功返回true</returns>
        public bool UpdateNodeConfig(OpcUaNodeConfigEntity nodeConfig)
        {
            return _repository.SaveOpcUaNodeConfig(nodeConfig);
        }

        /// <summary>
        /// 根据节点ID获取配置（兼容方法）
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <returns>节点配置</returns>
        public OpcUaNodeConfigEntity GetNodeConfigByNodeId(string nodeId)
        {
            return _repository.GetOpcUaNodeConfigByNodeId(nodeId);
        }

        /// <summary>
        /// 删除节点配置（兼容方法）
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <returns>删除成功返回true</returns>
        public bool DeleteNodeConfig(string nodeId)
        {
            var config = GetNodeConfigByNodeId(nodeId);
            if (config != null)
            {
                return _repository.DeleteOpcUaNodeConfig(config.Id);
            }
            return false;
        }

        /// <summary>
        /// 批量保存节点配置（兼容方法）
        /// </summary>
        /// <param name="nodeConfigs">节点配置列表</param>
        /// <returns>保存成功的行数</returns>
        public int BatchSaveNodeConfigs(List<OpcUaNodeConfigEntity> nodeConfigs)
        {
            return _repository.SaveOpcUaNodeConfigs(nodeConfigs);
        }

        /// <summary>
        /// 获取所有节点配置（兼容方法）
        /// </summary>
        /// <returns>节点配置列表</returns>
        public List<OpcUaNodeConfigEntity> GetAllNodeConfigs()
        {
            return _repository.GetAllOpcUaNodeConfigs();
        }

        #endregion

        #region 数据迁移

        /// <summary>
        /// 从JSON配置文件迁移数据到数据库
        /// </summary>
        /// <param name="jsonFilePath">JSON文件路径</param>
        /// <returns>迁移成功返回true</returns>
        public bool MigrateFromJsonConfig(string jsonFilePath = "opcua_config.json")
        {
            if (!System.IO.Path.IsPathRooted(jsonFilePath))
            {
                jsonFilePath = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, jsonFilePath);
            }

            return _repository.MigrateFromJsonConfig(jsonFilePath);
        }

        /// <summary>
        /// 检查是否需要从JSON迁移数据
        /// </summary>
        /// <returns>需要迁移返回true</returns>
        public bool NeedMigration()
        {
            try
            {
                var nodes = GetAllNodes();
                return nodes == null || nodes.Count == 0;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// 初始化配置表
        /// </summary>
        public void InitializeTables()
        {
            _repository.InitializeOpcUaTables();
        }

        /// <summary>
        /// 检查是否有任何配置数据
        /// </summary>
        /// <returns>有配置数据返回true</returns>
        public bool HasAnyConfig()
        {
            try
            {
                var serverConfig = GetServerConfig();
                var nodeConfigs = GetAllNodes();
                return serverConfig != null || (nodeConfigs != null && nodeConfigs.Count > 0);
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region 兼容性方法 - 为了兼容原有的OpcUaNodeConfig类

        /// <summary>
        /// 将数据库实体转换为原有的配置类
        /// </summary>
        /// <param name="entity">数据库实体</param>
        /// <returns>原有配置类</returns>
        public OpcUaNodeConfig ToOpcUaNodeConfig(OpcUaNodeConfigEntity entity)
        {
            if (entity == null) return null;

            return new OpcUaNodeConfig
            {
                NodeId = entity.NodeId,
                Name = entity.Name,
                Description = entity.Description,
                DataType = entity.DataType,
                AccessLevel = entity.AccessLevel,
                IsSubscribed = entity.IsSubscribed,
                PropertyName = entity.PropertyName,
                ObjectName = entity.ObjectName,
                Group = entity.Group,
                ScanRate = entity.ScanRate > 0 ? entity.ScanRate : 1000,
                CanRead = entity.AccessLevel?.Contains("Read") ?? true,
                CanWrite = entity.AccessLevel?.Contains("Write") ?? false
            };
        }

        /// <summary>
        /// 获取所有节点配置（原有格式）
        /// </summary>
        /// <returns>原有格式的节点配置列表</returns>
        public List<OpcUaNodeConfig> GetAllNodesAsOldFormat()
        {
            var entities = GetAllNodes();
            return entities.Select(ToOpcUaNodeConfig).ToList();
        }

        #endregion

        #region OPC UA 数据写入方法（带类型转换）

        /// <summary>
        /// 写入节点数据（带类型转换）
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="value">要写入的值</param>
        /// <returns>写入结果</returns>
        public async Task<OperateResult> WriteNodeWithTypeConversionAsync(string nodeId, object value)
        {
            try
            {
                // 获取节点配置
                var nodeConfig = GetNodeConfigByNodeId(nodeId);
                if (nodeConfig == null)
                {
                    return new OperateResult($"未找到节点配置: {nodeId}");
                }

                // 根据节点配置进行类型转换
                var convertedValue = ConvertValueByNodeConfig(nodeConfig, value);

                // 获取OPC UA客户端实例
                var opcUaService = OpcUaServiceManager.Instance;
                if (opcUaService == null)
                {
                    return new OperateResult("OPC UA服务未初始化");
                }

                // 写入转换后的值
                return await opcUaService.WriteNodeAsync(nodeId, convertedValue);
            }
            catch (Exception ex)
            {
                return new OperateResult($"写入节点失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 批量写入节点数据（带类型转换）
        /// </summary>
        /// <param name="nodeValues">节点ID和值的字典</param>
        /// <returns>写入结果</returns>
        public async Task<OperateResult> WriteNodesWithTypeConversionAsync(Dictionary<string, object> nodeValues)
        {
            try
            {
                var nodeIds = new List<string>();
                var values = new List<object>();

                foreach (var kvp in nodeValues)
                {
                    var nodeId = kvp.Key;
                    var value = kvp.Value;

                    // 获取节点配置
                    var nodeConfig = GetNodeConfigByNodeId(nodeId);
                    if (nodeConfig == null)
                    {
                        return new OperateResult($"未找到节点配置: {nodeId}");
                    }

                    // 根据节点配置进行类型转换
                    var convertedValue = ConvertValueByNodeConfig(nodeConfig, value);

                    nodeIds.Add(nodeId);
                    values.Add(convertedValue);
                }

                // 获取OPC UA客户端实例
                var opcUaService = OpcUaServiceManager.Instance;
                if (opcUaService == null)
                {
                    return new OperateResult("OPC UA服务未初始化");
                }

                // 批量写入转换后的值
                return await opcUaService.WriteNodesAsync(nodeIds.ToArray(), values.ToArray());
            }
            catch (Exception ex)
            {
                return new OperateResult($"批量写入节点失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 根据节点配置转换值类型
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        /// <param name="value">原始值</param>
        /// <returns>转换后的值</returns>
        private object ConvertValueByNodeConfig(OpcUaNodeConfigEntity nodeConfig, object value)
        {
            if (nodeConfig == null || string.IsNullOrEmpty(nodeConfig.DataType))
            {
                return value;
            }

            try
            {
                return ConvertValue(value, nodeConfig.DataType);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"节点 {nodeConfig.NodeId} 类型转换失败，期望类型: {nodeConfig.DataType}，实际值: {value}，错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 根据数据类型字符串转换值
        /// </summary>
        /// <param name="value">要转换的值</param>
        /// <param name="dataType">目标数据类型</param>
        /// <returns>转换后的值</returns>
        private object ConvertValue(object value, string dataType)
        {
            if (value == null)
            {
                return GetDefaultValue(dataType);
            }

            // 如果已经是目标类型，直接返回
            var targetType = GetTypeFromString(dataType);
            if (targetType != null && targetType.IsAssignableFrom(value.GetType()))
            {
                return value;
            }

            switch (dataType.ToLower())
            {
                case "boolean":
                case "bool":
                    return Convert.ToBoolean(value);
                case "byte":
                    return Convert.ToByte(value);
                case "sbyte":
                    return Convert.ToSByte(value);
                case "int16":
                case "short":
                    return Convert.ToInt16(value);
                case "uint16":
                case "ushort":
                    return Convert.ToUInt16(value);
                case "int32":
                case "int":
                    return Convert.ToInt32(value);
                case "uint32":
                case "uint":
                    return Convert.ToUInt32(value);
                case "int64":
                case "long":
                    return Convert.ToInt64(value);
                case "uint64":
                case "ulong":
                    return Convert.ToUInt64(value);
                case "float":
                case "single":
                    return Convert.ToSingle(value);
                case "double":
                    return Convert.ToDouble(value);
                case "decimal":
                    return Convert.ToDecimal(value);
                case "string":
                    return Convert.ToString(value);
                case "datetime":
                    return Convert.ToDateTime(value);
                default:
                    // 尝试使用反射进行转换
                    if (targetType != null)
                    {
                        return Convert.ChangeType(value, targetType);
                    }
                    return value;
            }
        }

        /// <summary>
        /// 根据数据类型字符串获取对应的Type
        /// </summary>
        /// <param name="dataType">数据类型字符串</param>
        /// <returns>对应的Type，如果未找到返回null</returns>
        private Type GetTypeFromString(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "boolean":
                case "bool":
                    return typeof(bool);
                case "byte":
                    return typeof(byte);
                case "sbyte":
                    return typeof(sbyte);
                case "int16":
                case "short":
                    return typeof(short);
                case "uint16":
                case "ushort":
                    return typeof(ushort);
                case "int32":
                case "int":
                    return typeof(int);
                case "uint32":
                case "uint":
                    return typeof(uint);
                case "int64":
                case "long":
                    return typeof(long);
                case "uint64":
                case "ulong":
                    return typeof(ulong);
                case "float":
                case "single":
                    return typeof(float);
                case "double":
                    return typeof(double);
                case "decimal":
                    return typeof(decimal);
                case "string":
                    return typeof(string);
                case "datetime":
                    return typeof(DateTime);
                default:
                    return null;
            }
        }

        /// <summary>
        /// 获取数据类型的默认值
        /// </summary>
        /// <param name="dataType">数据类型</param>
        /// <returns>默认值</returns>
        private object GetDefaultValue(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "boolean":
                case "bool":
                    return false;
                case "byte":
                    return (byte)0;
                case "sbyte":
                    return (sbyte)0;
                case "int16":
                case "short":
                    return (short)0;
                case "uint16":
                case "ushort":
                    return (ushort)0;
                case "int32":
                case "int":
                    return 0;
                case "uint32":
                case "uint":
                    return 0u;
                case "int64":
                case "long":
                    return 0L;
                case "uint64":
                case "ulong":
                    return 0UL;
                case "float":
                case "single":
                    return 0.0f;
                case "double":
                    return 0.0;
                case "decimal":
                    return 0.0m;
                case "string":
                    return string.Empty;
                case "datetime":
                    return DateTime.MinValue;
                default:
                    return null;
            }
        }

        #endregion

        #region IDisposable实现

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed && disposing)
            {
                _repository?.Dispose();
                _repository = null;
            }
            _disposed = true;
        }

        #endregion
    }
}